package com.lxy.新特性.stream;

import com.lxy.mybatis.pojo.User.Emp;
import com.lxy.mybatis.pojo.User.EnumStatus;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest {
    @Test
    public void test() {
        /**
         * 原数据->流【1、创建，2、操作、3、终止流】->新数据
         * */
        Stream<Object> stream = new ArrayList<>().stream();

        //对象类型数组
        Emp[] emp = new Emp[10];
        Stream<Emp> stream1 = Arrays.stream(emp);

        Emp emp1 = new Emp();
        Stream<Object> objectStream = Stream.of(emp1);

        //创建无限流 1、迭代
        Stream.iterate(0, i -> i + 1).limit(10).forEach(System.out::println);
        //2、生成
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }

    //初始化员工数据
    List<Emp> tmp = Arrays.asList(
            new Emp(1,"lxy",2,'女',"123@qq.com", EnumStatus.CLOSE),
            new Emp(2,"lili",21,'女',"456@qq.com", EnumStatus.OPEN),
            new Emp(3,"lucy",21,'女',"789@qq.com", EnumStatus.CLOSE),
            new Emp(4,"pite",41,'男',"101@qq.com", EnumStatus.OPEN),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",EnumStatus.OPEN),
            new Emp(8,"qiqi",1,'女',"110@qq.com",EnumStatus.CLOSE)
    ) ;

    @Test
    public void test2() {
        //惰性求值计算
        Stream<Emp> empStream = tmp.stream().filter(emp -> emp.getAge() > 20).limit(3);//找到满足条件个数的值就不再进行迭代
        empStream.forEach(System.out::println);

        //注：跳过的个数不能大于查出来的总数
        tmp.stream().filter(emp -> emp.getAge() > 20).skip(6).forEach(System.out::println);

        tmp.stream().filter(emp -> emp.getAge() > 20).distinct().forEach(System.out::println);//找到满足条件个数的值就不再进行迭代
    }

//    外部迭代
    @Test
    public void test3() {
        Iterator<Emp> iterator = tmp.iterator();
        while (iterator.hasNext()) {
            Emp emp = iterator.next();
            System.out.println(emp.toString());
        }
    }

    List<String> list = Arrays.asList("higk","abc", "def");

    @Test
    public void test4() {
        //静态类::实力方法 -> String emp.getEmpName(空参)
        //函数式接口作用到集合每个对象中，并返回新数据
        tmp.stream().map(Emp::getEmpName).forEach(System.out::println);
    }

    @Test
    public void test4_1(){
        List<String> list = Arrays.asList("abc", "def");
        List listFlash = new ArrayList<>();
        listFlash.add(1);
//        listFlash.add(list); //1、[abc, def]
        listFlash.addAll(list); //1、abc、def

        listFlash.forEach(System.out::println);
    }


    @Test
    public void test5() {
        //把Stream 集合中的数据拆包放到Stream中
        list.stream().flatMap(StreamTest::addAll).forEach(System.out::println);
    }
    //String -> Char
    public static Stream<Character> addAll(String str){
        List<Character> list = new ArrayList<>();
        for (int i = 0; i < str.length(); i++) {
            list.add(str.charAt(i));
        }
        return list.stream();
    }

    @Test
    public void test6() {
        //自然排序Comparable
        list.stream().sorted().forEach(System.out::println);

        //定制排序Comparator
        tmp.stream().sorted((x,y) -> {
            if(x.getAge().equals(y.getAge())){
                return x.getEmpName().compareTo(y.getEmpName());
            }
            else{
                return x.getAge().compareTo(y.getAge());
            }
        });
    }

    //初始化员工数据
    List<Emp> tmp1 = Arrays.asList(
            new Emp(1,"lxy",2,'女',"123@qq.com",12000.0, EnumStatus.CLOSE),
            new Emp(2,"lili",21,'女',"456@qq.com",22000.0, EnumStatus.OPEN),
            new Emp(3,"lucy",21,'女',"789@qq.com",32000.0, EnumStatus.CLOSE),
            new Emp(4,"pite",41,'男',"101@qq.com", 42000.0,EnumStatus.OPEN),
            new Emp(4,"pite",41,'男',"101@qq.com",52000.0,EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",62000.0,EnumStatus.FREE),
            new Emp(4,"pite",41,'男',"101@qq.com",12000.0,EnumStatus.OPEN),
            new Emp(8,"qiqi",1,'女',"110@qq.com",72000.0,EnumStatus.CLOSE)
    ) ;

    //终止操作
    @Test
    public void test7() {
        //检查是否匹配所有元素
        boolean b = tmp.stream().allMatch(e -> e.getEnumStatus().equals(EnumStatus.CLOSE));
        System.out.println("检查是否匹配所有元素 all"+b);

        boolean b1 = tmp.stream().anyMatch(e -> e.getEnumStatus().equals(EnumStatus.CLOSE));
        System.out.println("检查是否匹配至少一个元素 any"+b1);

        boolean b2 = tmp.stream().noneMatch(e -> e.getEnumStatus().equals(EnumStatus.CLOSE));
        System.out.println("检查是否没有匹配所以要元素 none"+b1);

        //Optional 安全返回 ,注：sorted 要求 Emp要么实现Comparator，要么显示指定
        Optional<Emp> first = tmp.stream().sorted(Comparator.comparing(Emp::getEmpName)).findFirst();
        System.out.println("返回第一个元素 "+first.get().getEmpName());

        Optional<Emp> any = tmp.stream().filter(e -> e.getEnumStatus().equals(EnumStatus.CLOSE)).findAny();
        System.out.println("返回当前流任一元素 "+any.get().getEmpName());

        long count = tmp.stream().count();
        System.out.println("返回当前流中元素总个数 "+count);

        //返回最多工资的员工对象，有可能为空的值，存储到Optional中
        Optional<Emp> max = tmp.stream().max((x, y) -> x.getSalary().compareTo(y.getSalary()));
        System.out.println("返回流中最大值 "+max.get().getEmpName());

        //返回最少工资的员工工资
        Optional<Double> min = tmp.stream().map(Emp::getSalary).min(Double::compareTo);
        System.out.println("返回流中最小值 "+min.get());

        List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        // i = 0; i=i+(x+y);
        Integer reduce = nums.stream().reduce(0, (x, y) -> x + y);
        System.out.println("归约 "+reduce);

        Optional<Double> reduce1 = tmp1.stream().map(Emp::getSalary).reduce(Double::sum);
        System.out.println("业务：当前公司员工所有工资总和【大数据-猜你喜欢】： "+reduce1.get());
    }

    @Test
    public void test8() {
        //Collectors是collect接口实现类
        //业务：将所有的名字收集到list中
         tmp1.stream().distinct().map(Emp::getEmpName).collect(Collectors.toList()).forEach(System.out::println);
         //存放到set中
         tmp1.stream().distinct().map(Emp::getEmpName).collect(Collectors.toSet()).forEach(System.out::println);
         //存放到特殊集合中
         tmp1.stream().distinct().map(Emp::getEmpName).collect(Collectors.toCollection(HashSet::new)).forEach(System.out::println);
        Long collect = tmp1.stream().distinct().map(Emp::getEmpName).collect(Collectors.counting());
        System.out.println("总数 "+collect);
        //平均值
        Double collect1 = tmp1.stream().collect(Collectors.averagingDouble(Emp::getSalary));
        System.out.println("平均值 = "+collect1);
        //总和
        Double collectsum = tmp1.stream().collect(Collectors.summingDouble(Emp::getSalary));
        System.out.println("总和 = "+collectsum);
        Optional<Emp> collectMax = tmp1.stream().collect(Collectors.maxBy((x,y)-> Double.compare(x.getSalary(),y.getSalary())));
        System.out.println("最大值 = "+collectMax.get().getSalary());
        Optional<Double> collectMin = tmp1.stream().map(Emp::getSalary).collect(Collectors.minBy(Double::compare));
        System.out.println("最小值 = "+collectMin.get());

        //业务：根据状态进行分组
        Map<EnumStatus, List<Emp>> collect2 = tmp1.stream().collect(Collectors.groupingBy(Emp::getEnumStatus));
        System.out.println(collect2);

        //多级分组 groupingBy(多个条件)
        Map<EnumStatus, Map<String, List<Emp>>> collect3 = tmp1.stream().collect(Collectors.groupingBy(Emp::getEnumStatus, Collectors.groupingBy((Emp e) -> {
            if (e.getAge() < 18) {
                return "青年";
            } else if (e.getAge() < 25) {
                return "中年";
            } else {
                return "老年";
            }
        })));

        System.out.println(collect3);

        //分区 partitioningBy 【false,true】
        Map<Boolean, List<Emp>> collect4 = tmp1.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 10000));
        System.out.println(collect4);

        //组函数
        DoubleSummaryStatistics collect5 = tmp1.stream().collect(Collectors.summarizingDouble(Emp::getSalary));
        System.out.println(collect5.getSum());
        System.out.println(collect5.getAverage());
        System.out.println(collect5.getMax());
        System.out.println(collect5.getMin());
        System.out.println(collect5.getCount());

        String collect6 = tmp1.stream().map(Emp::getEmpName).collect(Collectors.joining(",", "首", "尾"));
        System.out.println(collect6);
    }

    @Test
    public void test9() {
        List<Integer> nums = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        nums.stream().map(num -> num * num).forEach(System.out::println);

        //数组写法
        Integer[] arr = new Integer[]{1,2,3,4,5,6,7,8,9,10};
        //在Arrays中arr作为参数存在
        Arrays.stream(arr).map(num -> num * num).forEach(System.out::println);

        DoubleSummaryStatistics collect = tmp1.stream().collect(Collectors.summarizingDouble(Emp::getSalary));
        System.out.println(collect.getCount());

        Optional<Integer> reduce = tmp1.stream().map(e -> 1).reduce(Integer::sum);
        System.out.println("reduce 存放 函数式接口 "+reduce.get());
    }
}
